package br.com.sgi.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import br.com.sgi.autentication.UsuarioLogado;
import br.com.sgi.dao.VisitanteDao;
import br.com.sgi.model.Visitante;
import br.com.sgi.service.VisitanteService;
import br.com.sgi.util.DateUtil;
import br.com.sgi.vo.MembroVo;
import br.com.sgi.vo.ParametroPesquisa;

@Service("visitanteService")
public class VisitanteServiceImpl implements VisitanteService {

	@Autowired
	private VisitanteDao visitanteDao;

	/**
	 * entityManager
	 */
	@PersistenceContext
	private EntityManager entityManager;

	private void apenasVisitante(StringBuffer sql) {
		sql.append("\n AND v.eMembro = 'N' ");

	}

	private void apenasVisitanteAtivo(StringBuffer sql, Map<String, Object> params) {
		sql.append("\n AND v.inativo = :inativo ");
		params.put("inativo", false);

	}

	@Override
	public void atualizar(Visitante visitante) {
		visitanteDao.update(visitante);
	}

	@Override
	public List<MembroVo> buscarAniversariantesDia(boolean contemEmail) {
		Map<String, Object> params = new HashMap<String, Object>();

		params.put("username", UsuarioLogado.getCoUsuario());
		params.put("coIgreja", UsuarioLogado.getCoIgrejaLocal());
		params.put("coSistema", UsuarioLogado.getCoSistema());

		StringBuffer sql = new StringBuffer();
		sql.append("\n SELECT new br.com.sgi.vo.MembroVo( v )  FROM Visitante v");
		sql.append("\n WHERE v.igrejaPertence.sistema.coSeqSistema =:coSistema");

		apenasVisitante(sql);
		apenasVisitanteAtivo(sql, params);

		if (contemEmail) {
			sql.append("\n AND v.email != '' ");
		}

		sql
				.append("\n AND (v.igrejaPertence.coSeqIgreja = :coIgreja OR v.igrejaPertence.coSeqIgreja in(SELECT ui.igreja.coSeqIgreja from UsersIgreja ui WHERE ui.users.username= :username)) ");
		sql.append("\n AND  Extract(Day From dt_nascimento) = Extract(Day From Now()) ");
		sql.append("\n AND  Extract(Month From dt_nascimento) = Extract(Month From Now()) ");
		sql.append(" order by v.nome");

		Query consulta = this.entityManager.createQuery(sql.toString());

		for (Entry<String, Object> entry : params.entrySet()) {
			consulta.setParameter(entry.getKey(), entry.getValue());
		}

		return consulta.getResultList();

	}

	@Override
	public List<MembroVo> buscarAniversariantesMes(boolean contemEmail) {
		Map<String, Object> params = new HashMap<String, Object>();

		params.put("username", UsuarioLogado.getCoUsuario());
		params.put("coIgreja", UsuarioLogado.getCoIgrejaLocal());
		params.put("coSistema", UsuarioLogado.getCoSistema());

		StringBuffer sql = new StringBuffer();
		sql.append("\n SELECT new br.com.sgi.vo.MembroVo( v )  FROM Visitante v");
		sql.append("\n join v.igrejaPertence i ");
		sql.append("\n join i.sistema s ");

		sql.append("\n WHERE  Extract(Month From dt_nascimento) = Extract(Month From Now())");

		sql.append("\n AND s.coSeqSistema =:coSistema ");

		apenasVisitante(sql);
		apenasVisitanteAtivo(sql, params);

		if (contemEmail) {
			sql.append("\n AND v.email != '' ");
		}

		sql
				.append(" \n AND (i.coSeqIgreja = :coIgreja "
						+ "	OR i.coSeqIgreja in(SELECT ui.igreja.coSeqIgreja from UsersIgreja ui WHERE ui.users.username= :username)) ");
		sql.append(" order by v.dtNascimento");

		Query consulta = this.entityManager.createQuery(sql.toString());

		for (Entry<String, Object> entry : params.entrySet()) {
			consulta.setParameter(entry.getKey(), entry.getValue());
		}

		return consulta.getResultList();

	}

	@Override
	public List<MembroVo> buscarAniversariantesMes(int mes, Long coIgreja) {
		Map<String, Object> params = new HashMap<String, Object>();

		params.put("username", UsuarioLogado.getCoUsuario());
		params.put("coIgreja", coIgreja);
		params.put("coSistema", UsuarioLogado.getCoSistema());

		StringBuffer sql = new StringBuffer();
		sql.append("\n SELECT new br.com.sgi.vo.MembroVo( v )  FROM Visitante v");
		sql.append("\n join v.igrejaPertence i ");
		sql.append("\n join i.sistema s ");
		sql.append("\n WHERE extract( month from v.dtNascimento ) = :mes ");

		apenasVisitante(sql);
		apenasVisitanteAtivo(sql, params);

		if (mes == -1) {
			sql.append("\n AND  Extract(Month From dt_nascimento) = Extract(Month From Now())");
		} else {
			sql.append("\n AND extract( month from v.dtNascimento ) = :mes ");
		}

		sql.append("\n AND s.coSeqSistema =:coSistema ");
		if (coIgreja != null) {
			params.put("coIgrejaPertence", coIgreja);
			sql.append("\n AND i.coSeqIgreja =:coIgrejaPertence ");
		}

		sql
				.append(" \n AND (i.coSeqIgreja = :coIgreja "
						+ "	OR i.coSeqIgreja in(SELECT ui.igreja.coSeqIgreja from UsersIgreja ui WHERE ui.users.username= :username)) ");
		sql.append(" order by v.dtNascimento");
		params.put("mes", mes);

		Query consulta = this.entityManager.createQuery(sql.toString());

		for (Entry<String, Object> entry : params.entrySet()) {
			consulta.setParameter(entry.getKey(), entry.getValue());
		}

		return consulta.getResultList();

	}

	@Override
	public List<Visitante> buscarVisitantesPorFiltro(String nome, Date dtNascimento,
			Date dtCadastro, Long coIgreja, String status) {
		Map<String, Object> params = new java.util.HashMap<String, Object>();
		StringBuffer sql = new StringBuffer();

		params.put("eMembro", "N");

		sql.append(" SELECT v FROM Visitante v ");
		sql.append(" inner join v.igrejaPertence i ");
		sql.append(" inner join i.sistema s ");
		sql.append(" WHERE s.coSeqSistema =:coSistema");
		sql.append(" AND v.eMembro = :eMembro ");

		apenasVisitante(sql);

		if (nome != null && !nome.isEmpty()) {
			sql.append(" AND upper(v.nome)  like :nome");
			params.put("nome", "%" + nome.toUpperCase() + "%");
		}
		if (dtNascimento != null) {
			sql.append(" AND v.dtNascimento = :dtNascimento");
			params.put("dtNascimento", dtNascimento);
		}
		if (coIgreja != null) {
			sql.append(" AND (i.coSeqIgreja = :coIgreja )");
			params.put("coIgreja", coIgreja);
		}
		if (!"".equals(status)) {
			if ("I".equals(status)) {
				sql.append(" AND (v.inativo = 'S' )");
			} else {
				sql.append(" AND (v.inativo = 'N' )");
			}

		}
		if (coIgreja == null) {
			sql
					.append(" AND (i.coSeqIgreja = :coIgreja or i.coSeqIgreja in(SELECT ui.igreja.coSeqIgreja from UsersIgreja ui WHERE ui.users.username= :username))");
			params.put("username", UsuarioLogado.getCoUsuario());
			params.put("coIgreja", UsuarioLogado.getCoIgrejaLocal());
		}
		sql.append("  order by v.nome )");

		return visitanteDao.findByNativeQuery(sql.toString(), params);
	}

	@Override
	public List<Visitante> buscarVisitantesPorUser() {
		Map<String, Object> params = new java.util.HashMap<String, Object>();
		params.put("username", UsuarioLogado.getCoUsuario());
		params.put("coIgreja", UsuarioLogado.getCoIgrejaLocal());
		return visitanteDao.findByNamedParams("buscarTodosVisitantes", params);
	}

	@Override
	public List<MembroVo> buscarVisitantesPorIgrejaComEmail( Long coIgreja){
		Map<String, Object> params = new HashMap<String, Object>();

		params.put("coSistema", UsuarioLogado.getCoSistema());

		StringBuffer sql = new StringBuffer();

		sql.append("\n SELECT new br.com.sgi.vo.MembroVo(v)  FROM Visitante v");
		sql.append("\n left join v.membroResponsavel m ");
		sql.append("\n join v.igrejaPertence i ");
		sql.append("\n join i.sistema s ");
		sql.append("\n WHERE s.coSeqSistema =:coSistema ");

			apenasVisitante(sql);

			if (coIgreja != null) {
				params.put("coIgrejaPertence", coIgreja);
				sql.append("\n AND i.coSeqIgreja =:coIgrejaPertence ");
			}else{
				params.put("coIgreja", UsuarioLogado.getCoIgrejaLocal());
				
				params.put("username", UsuarioLogado.getCoUsuario());
				
				sql
				.append(" \n AND (i.coSeqIgreja = :coIgreja "
						+ "	OR i.coSeqIgreja in(SELECT ui.igreja.coSeqIgreja from UsersIgreja ui WHERE ui.users.username= :username)) ");
			}
				

			sql.append("\n AND v.email != '' ");
			sql.append("\n AND v.inativo = 'N' ");

			Query consulta = this.entityManager.createQuery(sql.toString());

			for (Entry<String, Object> entry : params.entrySet()) {
				consulta.setParameter(entry.getKey(), entry.getValue());
			}
			return consulta.getResultList();
					
	}
	
	public List<MembroVo> buscaVisitanteDinamica(List<ParametroPesquisa> parametros, Long coIgreja,
			String status) {
		Map<String, Object> params = new HashMap<String, Object>();

		params.put("username", UsuarioLogado.getCoUsuario());
		params.put("coIgreja", UsuarioLogado.getCoIgrejaLocal());
		params.put("coSistema", UsuarioLogado.getCoSistema());

		StringBuffer sql = new StringBuffer();

		sql.append("\n SELECT new br.com.sgi.vo.MembroVo(v)  FROM Visitante v");
		sql.append("\n left join v.membroResponsavel m ");
		sql.append("\n join v.igrejaPertence i ");
		sql.append("\n join i.sistema s ");
		sql.append("\n WHERE s.coSeqSistema =:coSistema ");

		apenasVisitante(sql);

		if (coIgreja != null) {
			params.put("coIgrejaPertence", coIgreja);
			sql.append("\n AND i.coSeqIgreja =:coIgrejaPertence ");
		}

		if (!status.equals("")) {
			params.put("status", status.equals("I") ? true : false);
			sql.append("\n AND v.inativo = :status ");
		}

		sql
				.append(" \n AND (i.coSeqIgreja = :coIgreja "
						+ "	OR i.coSeqIgreja in(SELECT ui.igreja.coSeqIgreja from UsersIgreja ui WHERE ui.users.username= :username)) ");

		if (parametros != null && !parametros.isEmpty()) {
			sql.append("\n AND ");
			montaQueryComParamentros(parametros, params, sql);
		}

		

		Query consulta = this.entityManager.createQuery(sql.toString());

		for (Entry<String, Object> entry : params.entrySet()) {
			consulta.setParameter(entry.getKey(), entry.getValue());
		}
		return consulta.getResultList();
	}

	private void montaQueryComParamentros(List<ParametroPesquisa> parametros,
			Map<String, Object> params, StringBuffer sql) {
		int cont = 0;
		for (ParametroPesquisa pr : parametros) {
			cont++;
			switch (pr.getTpParamentro()) {
			case 1:
				sql.append(" ");
				sql.append("\n ");
				// sql.append( "\n to_date(");
				sql.append("v.");
				sql.append(pr.getOpcao());
				sql.append(" ");
				// sql.append(" , 'dd-mm-yyyy') ");
				sql.append(pr.getOperacao());
				sql.append(" ");
				sql.append("\n to_date('");
				sql.append(DateUtil.getDateStr2(pr.getDtPesquisa()));
				sql.append("', 'dd-mm-yyyy') ");
				// sql.append(" :");
				// sql.append(pr.getOpcao());
				sql.append(" ");
				if (cont < parametros.size()) {
					sql.append(pr.getJuncao());
				}
				sql.append(" ");
				// params.put(pr.getOpcao(), (Date)pr.getDtPesquisa());
				break;
			case 2:
				sql.append("\n ");
				sql.append("UPPER(v.");
				sql.append(pr.getOpcao());
				sql.append(")");
				sql.append(" like ");
				sql.append(" :");
				sql.append(pr.getOpcao());
				sql.append(" ");
				if (cont < parametros.size()) {
					sql.append(pr.getJuncao());
				}
				sql.append(" ");
				String dado = pr.getDado().toString().toUpperCase().trim() + "%";
				params.put(pr.getOpcao(), dado);
				break;
			case 3:
				sql.append("\n ");
				sql.append("v.");
				sql.append(pr.getOpcao());
				sql.append(" ");
				sql.append(pr.getOperacao());
				sql.append(":");
				sql.append(pr.getOpcao());
				sql.append(" ");
				if (cont < parametros.size()) {
					sql.append(pr.getJuncao());
				}
				sql.append(" ");
				if (pr.getDado() != null) {
					params.put(pr.getOpcao(), Long.valueOf(pr.getDado().toString()));
				} else {
					params.put(pr.getOpcao(), null);
				}
				break;
			default:
				break;
			}
		}
	}

	@Override
	public void excluir(Long coVisitante) {
		visitanteDao.deleteById(coVisitante);

	}

	@Override
	public boolean existeVisitanteNaIgreja(Long coIgreja) {
		List<Visitante> listVistante = buscarVisitantesPorFiltro(null, null, null, coIgreja, null);
		if (listVistante != null && listVistante.isEmpty()) {
			return false;
		}

		return true;
	}

	@Override
	public void salvar(Visitante visitante) {
		visitanteDao.save(visitante);

	}

	public List<String> visitantePorMembroResponsavel(Long coMembro) {
		Map<String, Object> params = new HashMap<String, Object>();

		params.put("coMembro", coMembro);

		StringBuffer sql = new StringBuffer();

		sql.append("\n SELECT v.nome FROM Visitante v");
		sql.append("\n left join v.membroResponsavel m ");
		sql.append("\n WHERE m.coSeqMembro = " + coMembro);
		Query consulta = this.entityManager.createQuery(sql.toString());

		return consulta.getResultList();
	}

}
